import ProductCommon from '@/api/ProductCommon';
import {
  Box,
  ClickModal,
  FormSection,
  Icon,
  useCall,
  useDictionary,
  useEffectState,
  useSimpleMemo,
} from '@/components';
import { defaultShouldUpdate, dictToMap, forkHandler } from '@/utils';
import { catchAndScrollFor } from '@/utils/fp';
import { Button, Form, Input, message, Table } from 'antd';
import { basename } from 'path';
import * as PropTypes from 'prop-types';
import React, { forwardRef, useEffect, useRef, useState } from 'react';
import SelectFactor from './SelectFactor';
import SelectFormulaTable from './SelectFormulaTable';

function render(Comp, row) {
  return (
    <Comp {...row.props}>
      <Button type='link'>{row.text}</Button>
    </Comp>
  );
}

SelectFormulaTableWithDownload = forwardRef(SelectFormulaTableWithDownload);
function SelectFormulaTableWithDownload(props, ref) {
  const fileUrl = props.attachment?.path || '';

  return (
    <>
      {!!fileUrl && (
        <Button href={fileUrl} target='_blank' size='small' type='link'>
          {basename(fileUrl)}
          <Icon type='download' fontSize={12} />
        </Button>
      )}
      <SelectFormulaTable ref={ref} {...props}>
        <Button size='small'>上传</Button>
      </SelectFormulaTable>
    </>
  );
}

const COLUMNS = [
  { dataIndex: 'name', align: 'center', width: '35%', title: '数据来源' },
  { dataIndex: 'component', align: 'center', width: '35%', title: '数据来源', render },
  { dataIndex: 'value', align: 'center', width: '30%', title: '名称/公式' },
];

function FormulaInput({ form }) {
  const validator = useCall((rule, value) =>
    ProductCommon.validateFormula(value, 'm', { hideMsg: 1 }).catch((error) => Promise.reject(error.msg)),
  );
  const rules = useSimpleMemo([
    { required: true, message: '请输入公式' },
    // { validator, message: '公式校验失败' },
  ]);

  const [hasFeedback, setState] = useState(false);
  const onValidate = useCall(
    forkHandler(
      () => {
        setState(true);
      },
      () => form.validateFields(['formula']),
      () =>
        validator(0, form.getFieldValue('formula')).catch((message) => {
          form.setFields([
            {
              name: 'formula',
              errors: [message],
            },
          ]);
        }),
      true,
    ),
  );

  return (
    <>
      <Form.Item name='formula' rules={rules} hasFeedback={hasFeedback}>
        <Input.TextArea
          onChange={() => {
            setState(false);
          }}
        />
      </Form.Item>
      <Box py={1}>
        <Button type='primary' onClick={onValidate}>
          验证公式
        </Button>
      </Box>
    </>
  );
}

const parseIfString = (string) => {
  try {
    return (typeof string === 'string' ? JSON.parse(string) : string) ?? null;
  } catch (e) {
    return null;
  }
};

FormulaConfig = forwardRef(FormulaConfig);

function FormulaConfig(props, ref) {
  const formulaTableRef = useRef();
  const factorRef = useRef();
  const {
    type = 'file',
    fileRequired = false,
    formulaData,
    formulaValue,
    relationCode,
    fileType,
    onOk,
    ...rest
  } = props;
  const [form] = Form.useForm();
  const [attachment, setAttachment] = useEffectState(formulaData?.attachment ?? null);
  const [list, setList] = useEffectState(formulaData?.list ?? null);
  const [ext, setExt] = useEffectState(
    /* formulaData?.parseArray ?? */
    parseIfString(formulaData?.productAttributeExt?.attributeValue) ?? null,
    defaultShouldUpdate,
  );
  const factorObjectMap = useDictionary('factorObject', false, dictToMap);

  const formulaValueMemo =
    (type === 'file' ? formulaData?.costCalculateFormula?.formulaExpression : formulaValue) ?? '';

  const allTableCode =
    list
      ?.map((v) => v.factorCode)
      .filter(Boolean)
      .join(', ') ?? null;
  const extValue =
    ext
      ?.map((v) => factorObjectMap?.[v.factorObject])
      .filter(Boolean)
      .join(', ') ?? null;

  useEffect(() => {
    if (formulaValueMemo) form.setFieldsValue({ formula: formulaValueMemo });
  }, [formulaValueMemo]);

  const onTableOk = useCall((data) => {
    setList(data.list);
    setAttachment(data.attachment);
  });

  const onFactorOk = useCall((selected) => {
    setExt(selected);
  });

  /*const onFormulaOk = useCall(async (selected) => {
   if (selected?.length) {
   const resp = await FormulaAPI.findByCode(selected[0].code);
   const list = resp?.data?.FormulaAndFactorPoolVo.list;
   }
   });*/

  const dataSource = useSimpleMemo([
    {
      name: '费率表',
      component: SelectFormulaTableWithDownload,
      text: attachment?.path,
      value: allTableCode,
      props: {
        ref: formulaTableRef,
        onOk: onTableOk,
        attachment,
        relationCode,
        fileType,
        list,
      },
    },
    {
      name: '对象因子',
      component: SelectFactor,
      text: '因子库',
      value: extValue,
      props: {
        ref: factorRef,
        onOk: onFactorOk,
      },
    },
    /*{
     name: '子公式',
     component: SelectFormula,
     text: '公式',
     value: parseArrayValue,
     props: {
     onOk: onFormulaOk,
     },
     },*/
  ]);

  const handleOk = useCall(async () => {
    const { formula } = await form.validateFields().catch(catchAndScrollFor(form));
    if (type === 'file') {
      if (!attachment && fileRequired) {
        formulaTableRef.current?.open?.();
        message.warn('请上传费率文件');
        return false;
      }
      onOk?.({
        attachment: {
          ...attachment,
          filtera: null,
        },
        list,
        costCalculateFormula: {
          ...formulaData?.costCalculateFormula,
          formulaType: fileType,
          formulaExpression: formula,
          formulaDesc: null,
          productCode: relationCode,
        },
        productAttributeExt: null, // { attributeValue: parseArray }
        formulaType: fileType,
        productCode: relationCode,
      });
    } else {
      onOk?.(formula);
    }
  });

  const content = (
    <>
      <Form form={form} component={false}>
        <Box flex dir='col' ali='stretch' layout='inline'>
          <FormSection title='公式表达式'>
            <FormulaInput form={form} />
          </FormSection>
        </Box>
      </Form>

      <FormSection title='变量'>
        <Table pagination={false} rowKey='name' columns={COLUMNS} dataSource={dataSource} />
      </FormSection>
    </>
  );
  return <ClickModal ref={ref} title='公式' forceRender {...rest} content={content} onOk={handleOk} />;
}

FormulaConfig.propTypes = {
  type: PropTypes.oneOf(['string', 'file']),
  fileRequired: PropTypes.bool,
  formulaData: PropTypes.object,
  formulaValue: PropTypes.string,
  relationCode: PropTypes.string,
  fileType: PropTypes.string,
  onOk: PropTypes.func,
};

export default FormulaConfig;
